/*
 * LinkLabel.java
 *
 *  created: 1.11.2011
 *  charset: UTF-8
 *  license: MIT (X11) (See LICENSE file for full license)
 */
package cz.mp.k3bg.gui.component;

import java.awt.Color;
import java.awt.Cursor;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.Icon;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.event.EventListenerList;

/**
 * Komponenta {@code LinkLabel} je popisek sloužící jako hypertextový odkaz.
 * 
 * @author Martin Pokorný
 * @version 0.1
 */
public class LinkLabel extends JLabel {

    /** Příznak zda bylo na odkaz aspoň jednou kliknuto. */
    private boolean visited = false;
    /** Příznak zda právě teď ukazuje kurzor myši na tento odkaz. */
    private boolean hover = false;
    
    private Color linkColor = Color.BLUE;
    /** Barva odkazu, na který bylo aspoň jednou kliknuto. */
    private Color visitedColor = Color.BLUE;
    /** Barva odkazu, v případě když na něj ukazuje kurzor myši. */
    private Color hoverColor = Color.BLUE;  
    
    
    
    // -----
    
    /** */
    public LinkLabel() {
        super();
        addMouseListener(new LinkMouseListener());
        setForegroundImpl(linkColor);
    }

    public LinkLabel(String text) {
        super(text);
        addMouseListener(new LinkMouseListener());
        setForegroundImpl(linkColor);        
    }

    public LinkLabel(String text, int horizontalAlignment) {
        super(text, horizontalAlignment);
        addMouseListener(new LinkMouseListener());
        setForegroundImpl(linkColor);        
    }

    public LinkLabel(String text, Icon icon, int horizontalAlignment) {
        super(text, icon, horizontalAlignment);
        addMouseListener(new LinkMouseListener());
        setForegroundImpl(linkColor);
    }

    
    
    // -----

    /**
     * 
     * @return 
     */
    public Color getLinkColor() {
        return linkColor;
    }
    
    /**
     * 
     * @param linkColor 
     */
    public void setLinkColor(Color linkColor) {
        if (linkColor == null) {
            throw new IllegalArgumentException("linkColor=null");
        }
        setForeground(linkColor);
        this.linkColor = linkColor;
    }
    
    /**
     * 
     * @return 
     */
    public Color getHoverColor() {
        return hoverColor;
    }
    
    /**
     * 
     * @param hoverColor 
     */
    public void setHoverColor(Color hoverColor) {
        if (hoverColor == null) {
            throw new IllegalArgumentException("hoverColor=null");
        }        
        this.hoverColor = hoverColor;
    }

    /**
     * 
     * @return 
     */
    public Color getVisitedColor() {
        return visitedColor;
    }

    /**
     * 
     * @param visitedColor 
     */
    public void setVisitedColor(Color visitedColor) {
        if (visitedColor == null) {
            throw new IllegalArgumentException("visitedColor=null");
        }
        this.visitedColor = visitedColor;
    }
    
    
    @Override
    public void setForeground(Color fg) {
        setForegroundImpl(fg);
    }
    
    /**
     * 
     * @param fg 
     */
    private void setForegroundImpl(Color fg) {
        if (fg != null) {
            super.setForeground(fg);
            repaint();
        }
    }     
    
    
    @Override
    protected void paintComponent(Graphics g) {
        // nakreslí původní popisek
        super.paintComponent(g);
     
        // nakreslí podtržení
        if (isEnabled()) {
            // šířka samotného textu = délka podtržení
            int width = SwingUtilities.computeStringWidth(
                    g.getFontMetrics(), this.getText());

            // horizontální posun za případnou ikonu
            int xIconOffset = 0;
            if (this.getIcon() != null) {
                // LEFT
                xIconOffset =
                        this.getIcon().getIconWidth() + this.getIconTextGap();
            }

            // x souřadnice počátku podtržení
            int x = 0;      // LEFT
            if (this.getHorizontalAlignment() == RIGHT) {
                x = this.getWidth() - width;
                xIconOffset = 0;
            }
            if (this.getHorizontalAlignment() == CENTER) {
                x = (this.getWidth() - width) / 2;
                xIconOffset = xIconOffset / 2;
            }
            
            int y = this.getBaseline(width, this.getHeight()) + 1;
            
            g.drawLine(
                    x + xIconOffset,         y,
                    x + xIconOffset + width, y);            
        }
    }
    
    // -----
    
    private EventListenerList listenersList = new EventListenerList();
    
    /**
     * Přidá <code>ActionListener</code> na tento odkaz.
     *
     * @param listener
     */
    public void addActionListener(ActionListener listener) {
         listenersList.add(ActionListener.class, listener);
    }

    /**
     * Odebere <code>ActionListener</code> z tenhoto odkazu.
     *
     * @param listener
     */
    public void removeActionListener(ActionListener listener) {
         listenersList.remove(ActionListener.class, listener);
    }

    /**
     * Vrátí seznam registovaných posluchačů <code>ActionListener</code>
     * přidaných metodou <code>addActionListener()</code>.
     *
     * @return
     */
    public ActionListener[] getActionListeners() {
        return listenersList.getListeners(ActionListener.class);
    }

    /**
     * Upozorní všechny registrované posluchače na událost.
     *
     * @param actionEvent
     */
    protected void fireActionPerformed(ActionEvent actionEvent) {
        Object[] listeners = listenersList.getListenerList();

        for (int i = listeners.length-2; i>=0; i-=2) {
            if (listeners[i] == ActionListener.class) {
                ((ActionListener) listeners[i+1]).actionPerformed(actionEvent);
            }
        }
    }    
    
    // -------------------------------------------------------------------------

    /**
     * Třída <code>LinkMouseListener</code> slouží pro obsluhu událostí
     * myši nad odkazem.
     */
    protected class LinkMouseListener extends MouseAdapter {

        /**
         * Klik na komponentu.
         *
         * @param e
         */
        @Override
        public void mouseClicked(MouseEvent e) {
            visited = true;
            hover = false;
            setForeground(visitedColor);

            fireActionPerformed(new ActionEvent(
                    LinkLabel.this,
                    e.getID(),
                    LinkLabel.this.getText(),
                    e.getWhen(),
                    e.getModifiers()) );
        }

        /**
         * Vstup kuzroru myši do oblasti nad komponentou.
         *
         * @param e
         */
        @Override
        public void mouseEntered(MouseEvent e) {
            setCursor(new Cursor(Cursor.HAND_CURSOR));
            hover = true;
            setForeground(hoverColor);
        }

        /**
         * Výstup kuzroru myši z oblasti nad komponentou.
         *
         * @param e
         */
        @Override
        public void mouseExited(MouseEvent e) {
            setCursor(Cursor.getDefaultCursor());
            hover = false;
            if (visited) {
                setForeground(visitedColor);
            }
            else {
                setForeground(linkColor);
            }
        }

    }   // LinkMouseListener
    
}   // LinkLabel.java

